﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Security.Principal;
using System.Web;

namespace NWebMock
{
    public class HttpContextWrapper : IHttpContext
    {
        #region Constructors

        public HttpContextWrapper(HttpContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            this.innerContext = context;
        }

        #endregion

        #region Fields

        private IHttpApplication innerApplication = null;
        private ICache innerCache = null;
        private HttpContext innerContext = null;
        private IProfileBase innerProfile = null;
        private IHttpRequest innerRequest = null;
        private IHttpResponse innerResponse = null;
        private IHttpServerUtility innerServer = null;
        private IHttpSessionState innerSession = null;
        private ITraceContext innerTrace = null;

        #endregion

        #region Properties

        public Exception[] AllErrors { get { return this.innerContext.AllErrors; } }

        public IHttpApplicationState Application { get { return this.ApplicationInstance.Application; } }

        public IHttpApplication ApplicationInstance
        {
            get
            {
                if (this.innerApplication != null)
                {
                    return this.innerApplication;
                }

                if (this.innerContext.ApplicationInstance != null)
                {
                    this.innerApplication = new HttpApplicationWrapper(this.innerContext.ApplicationInstance, this);
                }

                return this.innerApplication;
            }
        }

        public ICache Cache
        {
            get
            {
                if (this.innerCache != null)
                {
                    return this.innerCache;
                }

                if (this.innerContext.Cache != null)
                {
                    this.innerCache = new CacheWrapper(this.innerContext.Cache);
                }

                return this.innerCache;
            }
        }

        public IHttpHandler CurrentHandler { get { return this.innerContext.CurrentHandler; } }

        public RequestNotification CurrentNotification { get { return this.innerContext.CurrentNotification; } }

        public Exception Error { get { return this.innerContext.Error; } }

        public IHttpHandler Handler { get { return this.innerContext.Handler; } set { this.innerContext.Handler = value; } }

        public bool IsCustomErrorEnabled { get { return this.innerContext.IsCustomErrorEnabled; } }

        public bool IsDebuggingEnabled { get { return this.innerContext.IsDebuggingEnabled; } }

        public bool IsPostNotification { get { return this.innerContext.IsPostNotification; } }

        public IDictionary Items { get { return this.innerContext.Items; } }

        public IHttpHandler PreviousHandler { get { return this.innerContext.PreviousHandler; } }

        public IProfileBase Profile
        {
            get
            {
                if (this.innerProfile != null)
                {
                    return this.innerProfile;
                }

                if (this.innerContext.Profile != null)
                {
                    this.innerProfile = new ProfileBaseWrapper(this.innerContext.Profile);
                }

                return this.innerProfile;
            }
        }

        public IHttpRequest Request
        {
            get
            {
                if (this.innerRequest != null)
                {
                    return this.innerRequest;
                }

                if (this.innerContext.Request != null)
                {
                    this.innerRequest = new HttpRequestWrapper(this.innerContext.Request);
                }

                return this.innerRequest;
            }
        }

        public IHttpResponse Response
        {
            get
            {
                if (this.innerResponse != null)
                {
                    return this.innerResponse;
                }

                if (this.innerContext.Response != null)
                {
                    this.innerResponse = new HttpResponseWrapper(this.innerContext.Response);
                }

                return this.innerResponse;
            }
        }

        public IHttpServerUtility Server
        {
            get
            {
                if (this.innerServer != null)
                {
                    return this.innerServer;
                }

                if (this.innerContext.Server != null)
                {
                    this.innerServer = new HttpServerUtilityWrapper(this.innerContext.Server);
                }

                return this.innerServer;
            }
        }

        public IHttpSessionState Session
        {
            get
            {
                if (this.innerSession != null)
                {
                    return this.innerSession;
                }

                if (this.innerContext.Session != null)
                {
                    this.innerSession = new HttpSessionStateWrapper(this.innerContext.Session);
                }

                return this.innerSession;
            }
        }

        public bool SkipAuthorization { get { return this.innerContext.SkipAuthorization; } set { this.innerContext.SkipAuthorization = value; } }

        public DateTime Timestamp { get { return this.innerContext.Timestamp; } }

        public ITraceContext Trace
        {
            get
            {
                if (this.innerTrace != null)
                {
                    return this.innerTrace;
                }

                if (this.innerContext.Trace != null)
                {
                    this.innerTrace = new TraceContextWrapper(this.innerContext.Trace);
                }

                return this.innerTrace;
            }
        }

        public IPrincipal User { get { return this.innerContext.User; } set { this.innerContext.User = value; } }

        #endregion

        #region Methods

        public void AddError(Exception errorInfo)
        {
            this.innerContext.AddError(errorInfo);
        }

        public void ClearError()
        {
            this.innerContext.ClearError();
        }

        public object GetConfig(string name)
        {
            return this.innerContext.GetConfig(name);
        }

        public object GetSection(string sectionName)
        {
            return this.innerContext.GetSection(sectionName);
        }

        public void RemapHandler(IHttpHandler handler)
        {
            this.innerContext.RemapHandler(handler);
        }

        public void RewritePath(string path)
        {
            this.innerContext.RewritePath(path);
        }

        public void RewritePath(string path, bool rebaseClientPath)
        {
            this.innerContext.RewritePath(path, rebaseClientPath);
        }

        public void RewritePath(string filePath, string pathInfo, string queryString)
        {
            this.innerContext.RewritePath(filePath, pathInfo, queryString);
        }

        public void RewritePath(string filePath, string pathInfo, string queryString, bool setClientFilePath)
        {
            this.innerContext.RewritePath(filePath, pathInfo, queryString, setClientFilePath);
        }

        #endregion

        #region IServiceProvider Members

        object IServiceProvider.GetService(Type serviceType)
        {
            return ((IServiceProvider)this.innerContext).GetService(serviceType);
        }

        #endregion
    }
}
